package com.yunhe.marketing.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.github.stuxuhai.jpinyin.PinyinException;
import com.yunhe.marketing.constant.EnterpriseConsts;
import com.yunhe.marketing.model.EnterpriseUpload;
import com.yunhe.marketing.service.IDemandRepositoryService;
import com.yunhe.marketing.util.EnterpriseUploadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: DongWenYu
 * @Date: 2021/2/23 10:30
 */
// 有个很重要的点 UploadDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class UploadDataListener  extends AnalysisEventListener<EnterpriseUpload> {

    private static final Logger logger = LoggerFactory.getLogger(UploadDataListener.class);

    /**
     * 实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 3000;
    List<EnterpriseUpload> list = new ArrayList<EnterpriseUpload>();
    /**
     * 同一个excel表中可能存在相同的数据。
     */
    List<EnterpriseUpload> removeList = new ArrayList<EnterpriseUpload>();
    private IDemandRepositoryService demandRepositoryService = null;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param demandRepositoryService
     * @return  
     * @create 2021/2/23 11:24
     */
    public UploadDataListener(IDemandRepositoryService demandRepositoryService) {
        this.demandRepositoryService = demandRepositoryService;
    }


    /**
     * 这个每一条数据解析都会来调用
     * @param data 
     * @param context
     * @return void 
     * @create 2021/2/23 11:26
     */
    @Override
    public void invoke(EnterpriseUpload data, AnalysisContext context) {
        logger.debug("解析到一条数据:{}", JSON.toJSONString(data));
        if (!EnterpriseUploadUtil.isEmpty(data)) {
            for (EnterpriseUpload enterpriseUpload : list){
                if (data.equals(enterpriseUpload)){
                    EnterpriseUploadUtil.update(data,enterpriseUpload);
                    removeList.add(enterpriseUpload);
                }
            }
            list.add(data);
        }
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (list.size() >= BATCH_COUNT) {
            try {
                removeSameData(list,removeList);
                saveData();
            } catch (PinyinException e) {
                e.printStackTrace();
            }
            // 存储完成清理 list
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        try {
            removeSameData(list,removeList);
            saveData();
        } catch (PinyinException e) {
            e.printStackTrace();
        }
        logger.info("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() throws PinyinException {
        logger.info("{}条数据，开始存储数据库！", list.size());
        demandRepositoryService.upload(list, EnterpriseConsts.CHANNEL_SOURCE.SpontaneousImport.value());
    }

    /**
     * 移除相同数据
     */
    private void removeSameData( List<EnterpriseUpload> list ,  List<EnterpriseUpload> removeList) throws PinyinException {
        for (EnterpriseUpload enterpriseUpload : removeList){
            list.remove(enterpriseUpload);
        }
        removeList.clear();
    }

}
